/**
 * 后端错误码定义
 * 统一管理API服务的错误代码和错误消息
 */

"use strict";

// HTTP状态码映射
const HTTP_STATUS = {
  OK: 200,
  CREATED: 201,
  NO_CONTENT: 204,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  METHOD_NOT_ALLOWED: 405,
  CONFLICT: 409,
  UNPROCESSABLE_ENTITY: 422,
  TOO_MANY_REQUESTS: 429,
  INTERNAL_SERVER_ERROR: 500,
  BAD_GATEWAY: 502,
  SERVICE_UNAVAILABLE: 503,
  GATEWAY_TIMEOUT: 504
};

// 业务错误码定义
const ERROR_CODES = {
  // 通用错误 (10000-10999)
  UNKNOWN_ERROR: {
    code: 10000,
    message: "Unknown error occurred",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An unexpected error occurred in the system"
  },
  SYSTEM_BUSY: {
    code: 10001,
    message: "System is busy",
    httpStatus: HTTP_STATUS.SERVICE_UNAVAILABLE,
    description: "System is currently busy, please try again later"
  },
  INVALID_PARAMETERS: {
    code: 10002,
    message: "Invalid parameters",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "Request parameters are invalid or missing"
  },
  OPERATION_FAILED: {
    code: 10003,
    message: "Operation failed",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "The requested operation failed to complete"
  },
  RESOURCE_LOCKED: {
    code: 10004,
    message: "Resource is locked",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "The requested resource is currently locked"
  },
  RATE_LIMIT_EXCEEDED: {
    code: 10005,
    message: "Rate limit exceeded",
    httpStatus: HTTP_STATUS.TOO_MANY_REQUESTS,
    description: "Too many requests, please slow down"
  },

  // 认证和授权错误 (11000-11999)
  AUTHENTICATION_REQUIRED: {
    code: 11000,
    message: "Authentication required",
    httpStatus: HTTP_STATUS.UNAUTHORIZED,
    description: "Authentication is required to access this resource"
  },
  INVALID_CREDENTIALS: {
    code: 11001,
    message: "Invalid credentials",
    httpStatus: HTTP_STATUS.UNAUTHORIZED,
    description: "The provided credentials are invalid"
  },
  TOKEN_EXPIRED: {
    code: 11002,
    message: "Token expired",
    httpStatus: HTTP_STATUS.UNAUTHORIZED,
    description: "The authentication token has expired"
  },
  TOKEN_INVALID: {
    code: 11003,
    message: "Invalid token",
    httpStatus: HTTP_STATUS.UNAUTHORIZED,
    description: "The authentication token is invalid"
  },
  PERMISSION_DENIED: {
    code: 11004,
    message: "Permission denied",
    httpStatus: HTTP_STATUS.FORBIDDEN,
    description: "You don't have permission to access this resource"
  },
  ACCOUNT_LOCKED: {
    code: 11005,
    message: "Account locked",
    httpStatus: HTTP_STATUS.FORBIDDEN,
    description: "The user account has been locked"
  },
  ACCOUNT_DISABLED: {
    code: 11006,
    message: "Account disabled",
    httpStatus: HTTP_STATUS.FORBIDDEN,
    description: "The user account has been disabled"
  },
  SESSION_EXPIRED: {
    code: 11007,
    message: "Session expired",
    httpStatus: HTTP_STATUS.UNAUTHORIZED,
    description: "The user session has expired"
  },

  // 数据验证错误 (12000-12999)
  VALIDATION_ERROR: {
    code: 12000,
    message: "Validation error",
    httpStatus: HTTP_STATUS.UNPROCESSABLE_ENTITY,
    description: "Input data validation failed"
  },
  REQUIRED_FIELD_MISSING: {
    code: 12001,
    message: "Required field missing",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "One or more required fields are missing"
  },
  INVALID_FORMAT: {
    code: 12002,
    message: "Invalid format",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The data format is invalid"
  },
  VALUE_TOO_LONG: {
    code: 12003,
    message: "Value too long",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The input value exceeds maximum length"
  },
  VALUE_TOO_SHORT: {
    code: 12004,
    message: "Value too short",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The input value is below minimum length"
  },
  INVALID_EMAIL: {
    code: 12005,
    message: "Invalid email format",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The email address format is invalid"
  },
  INVALID_URL: {
    code: 12006,
    message: "Invalid URL format",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The URL format is invalid"
  },
  INVALID_DATE: {
    code: 12007,
    message: "Invalid date format",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The date format is invalid"
  },

  // 资源错误 (13000-13999)
  RESOURCE_NOT_FOUND: {
    code: 13000,
    message: "Resource not found",
    httpStatus: HTTP_STATUS.NOT_FOUND,
    description: "The requested resource was not found"
  },
  RESOURCE_ALREADY_EXISTS: {
    code: 13001,
    message: "Resource already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "A resource with the same identifier already exists"
  },
  RESOURCE_IN_USE: {
    code: 13002,
    message: "Resource in use",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "The resource is currently in use and cannot be modified"
  },
  RESOURCE_EXPIRED: {
    code: 13003,
    message: "Resource expired",
    httpStatus: HTTP_STATUS.GONE,
    description: "The requested resource has expired"
  },

  // 博客文章错误 (14000-14999)
  ARTICLE_NOT_FOUND: {
    code: 14000,
    message: "Article not found",
    httpStatus: HTTP_STATUS.NOT_FOUND,
    description: "The requested article was not found"
  },
  ARTICLE_TITLE_EXISTS: {
    code: 14001,
    message: "Article title already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "An article with this title already exists"
  },
  ARTICLE_SLUG_EXISTS: {
    code: 14002,
    message: "Article slug already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "An article with this slug already exists"
  },
  ARTICLE_SAVE_FAILED: {
    code: 14003,
    message: "Failed to save article",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while saving the article"
  },
  ARTICLE_PUBLISH_FAILED: {
    code: 14004,
    message: "Failed to publish article",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while publishing the article"
  },
  ARTICLE_DELETE_FAILED: {
    code: 14005,
    message: "Failed to delete article",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while deleting the article"
  },
  INVALID_ARTICLE_STATUS: {
    code: 14006,
    message: "Invalid article status",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The article status is invalid"
  },

  // 分类错误 (15000-15999)
  CATEGORY_NOT_FOUND: {
    code: 15000,
    message: "Category not found",
    httpStatus: HTTP_STATUS.NOT_FOUND,
    description: "The requested category was not found"
  },
  CATEGORY_NAME_EXISTS: {
    code: 15001,
    message: "Category name already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "A category with this name already exists"
  },
  CATEGORY_SLUG_EXISTS: {
    code: 15002,
    message: "Category slug already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "A category with this slug already exists"
  },
  CATEGORY_HAS_ARTICLES: {
    code: 15003,
    message: "Category has articles",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "Cannot delete category that contains articles"
  },
  CATEGORY_SAVE_FAILED: {
    code: 15004,
    message: "Failed to save category",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while saving the category"
  },
  CATEGORY_DELETE_FAILED: {
    code: 15005,
    message: "Failed to delete category",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while deleting the category"
  },

  // 标签错误 (16000-16999)
  TAG_NOT_FOUND: {
    code: 16000,
    message: "Tag not found",
    httpStatus: HTTP_STATUS.NOT_FOUND,
    description: "The requested tag was not found"
  },
  TAG_NAME_EXISTS: {
    code: 16001,
    message: "Tag name already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "A tag with this name already exists"
  },
  TAG_SLUG_EXISTS: {
    code: 16002,
    message: "Tag slug already exists",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "A tag with this slug already exists"
  },
  TAG_HAS_ARTICLES: {
    code: 16003,
    message: "Tag has articles",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "Cannot delete tag that is used by articles"
  },
  TAG_SAVE_FAILED: {
    code: 16004,
    message: "Failed to save tag",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while saving the tag"
  },
  TAG_DELETE_FAILED: {
    code: 16005,
    message: "Failed to delete tag",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while deleting the tag"
  },

  // 文件上传错误 (17000-17999)
  FILE_REQUIRED: {
    code: 17000,
    message: "File is required",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "A file must be provided for upload"
  },
  FILE_TOO_LARGE: {
    code: 17001,
    message: "File too large",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The uploaded file exceeds the maximum size limit"
  },
  FILE_TYPE_NOT_ALLOWED: {
    code: 17002,
    message: "File type not allowed",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The file type is not supported"
  },
  FILE_UPLOAD_FAILED: {
    code: 17003,
    message: "File upload failed",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while uploading the file"
  },
  FILE_NOT_FOUND: {
    code: 17004,
    message: "File not found",
    httpStatus: HTTP_STATUS.NOT_FOUND,
    description: "The requested file was not found"
  },
  FILE_DELETE_FAILED: {
    code: 17005,
    message: "Failed to delete file",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while deleting the file"
  },
  INVALID_FILE_NAME: {
    code: 17006,
    message: "Invalid file name",
    httpStatus: HTTP_STATUS.BAD_REQUEST,
    description: "The file name contains invalid characters"
  },

  // 数据库错误 (18000-18999)
  DATABASE_CONNECTION_ERROR: {
    code: 18000,
    message: "Database connection error",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "Failed to connect to the database"
  },
  DATABASE_QUERY_ERROR: {
    code: 18001,
    message: "Database query error",
    httpStatus: HTTP_STATUS.INTERNAL_SERVER_ERROR,
    description: "An error occurred while executing database query"
  },
  DATABASE_CONSTRAINT_ERROR: {
    code: 18002,
    message: "Database constraint violation",
    httpStatus: HTTP_STATUS.CONFLICT,
    description: "The operation violates database constraints"
  },
  DATABASE_TIMEOUT: {
    code: 18003,
    message: "Database operation timeout",
    httpStatus: HTTP_STATUS.GATEWAY_TIMEOUT,
    description: "The database operation timed out"
  },

  // 外部服务错误 (19000-19999)
  EXTERNAL_SERVICE_ERROR: {
    code: 19000,
    message: "External service error",
    httpStatus: HTTP_STATUS.BAD_GATEWAY,
    description: "An error occurred while calling external service"
  },
  EXTERNAL_SERVICE_TIMEOUT: {
    code: 19001,
    message: "External service timeout",
    httpStatus: HTTP_STATUS.GATEWAY_TIMEOUT,
    description: "External service request timed out"
  },
  EXTERNAL_SERVICE_UNAVAILABLE: {
    code: 19002,
    message: "External service unavailable",
    httpStatus: HTTP_STATUS.SERVICE_UNAVAILABLE,
    description: "The external service is currently unavailable"
  }
};

/**
 * 根据错误码获取错误信息
 * @param {number} code - 错误码
 * @returns {Object|null} 错误信息对象
 */
function getErrorByCode(code) {
  for (const key in ERROR_CODES) {
    if (ERROR_CODES[key].code === code) {
      return ERROR_CODES[key];
    }
  }
  return null;
}

/**
 * 根据错误名称获取错误信息
 * @param {string} name - 错误名称
 * @returns {Object|null} 错误信息对象
 */
function getErrorByName(name) {
  return ERROR_CODES[name] || null;
}

/**
 * 创建错误对象
 * @param {string|number} codeOrName - 错误码或错误名称
 * @param {string} customMessage - 自定义错误消息
 * @param {Object} details - 错误详情
 * @returns {Object} 标准错误对象
 */
function createError(codeOrName, customMessage = null, details = null) {
  let errorInfo;

  if (typeof codeOrName === 'number') {
    errorInfo = getErrorByCode(codeOrName);
  } else {
    errorInfo = getErrorByName(codeOrName);
  }

  if (!errorInfo) {
    errorInfo = ERROR_CODES.UNKNOWN_ERROR;
  }

  return {
    code: errorInfo.code,
    message: customMessage || errorInfo.message,
    httpStatus: errorInfo.httpStatus,
    description: errorInfo.description,
    details,
    timestamp: new Date().toISOString()
  };
}

/**
 * 创建Moleculer错误对象
 * @param {string|number} codeOrName - 错误码或错误名称
 * @param {string} customMessage - 自定义错误消息
 * @param {Object} details - 错误详情
 * @returns {MoleculerError} Moleculer错误对象
 */
function createMoleculerError(codeOrName, customMessage = null, details = null) {
  const { MoleculerError } = require("moleculer").Errors;
  const errorInfo = createError(codeOrName, customMessage, details);

  return new MoleculerError(
    errorInfo.message,
    errorInfo.code,
    null,
    {
      httpStatus: errorInfo.httpStatus,
      description: errorInfo.description,
      details: errorInfo.details,
      timestamp: errorInfo.timestamp
    }
  );
}

/**
 * 检查是否为业务错误
 * @param {number} code - 错误码
 * @returns {boolean} 是否为业务错误
 */
function isBusinessError(code) {
  return code >= 10000 && code < 20000;
}

/**
 * 检查是否为系统错误
 * @param {number} code - 错误码
 * @returns {boolean} 是否为系统错误
 */
function isSystemError(code) {
  return code >= 18000 && code < 19000;
}

/**
 * 检查是否为验证错误
 * @param {number} code - 错误码
 * @returns {boolean} 是否为验证错误
 */
function isValidationError(code) {
  return code >= 12000 && code < 13000;
}

/**
 * 检查是否为认证错误
 * @param {number} code - 错误码
 * @returns {boolean} 是否为认证错误
 */
function isAuthError(code) {
  return code >= 11000 && code < 12000;
}

/**
 * 获取错误类型
 * @param {number} code - 错误码
 * @returns {string} 错误类型
 */
function getErrorType(code) {
  if (isAuthError(code)) return 'auth';
  if (isValidationError(code)) return 'validation';
  if (isSystemError(code)) return 'system';
  if (isBusinessError(code)) return 'business';
  return 'unknown';
}

module.exports = {
  HTTP_STATUS,
  ERROR_CODES,
  getErrorByCode,
  getErrorByName,
  createError,
  createMoleculerError,
  isBusinessError,
  isSystemError,
  isValidationError,
  isAuthError,
  getErrorType
};